<?php


namespace common\service;

use common\model\EntityModel;
use common\model\TaskModel;
use common\model\UserModel;
use support\SingletonTrait;

class DepartmentReportService
{
    use SingletonTrait;

    /**
     * 部门报表-列表
     * @param $filter
     * @return array
     */
    public function list($filter)
    {

        $departmentUserList = $this->getDepartmentUserList($filter['department_id']);
        if (empty($departmentUserList)) { // 没有查到当前部门下的用户
            return [];
        }
        // 如果不是查区间 - month 必须是月份开始时间
        if (!empty($filter['month'])) {

            $monthStartTime = strtotime('-1 month', strtotime($filter['month']));
            $monthEndTime = strtotime("+1 month", strtotime($filter['month']));
            $filter['start_time'] = $monthStartTime;
            $filter['end_time'] = $monthEndTime;
            $dingStartTime = strtotime($filter['month']);
        } else {
            $filter['start_time'] = $dingStartTime = strtotime($filter['start_time']);
            $filter['end_time'] = strtotime('+1 month', strtotime($filter['end_time']));
        }

        // 查询钉钉工时
        $paramData = [
            'user_id_list' => array_column($departmentUserList, 'im_user_id'),
            'work_date_from' => date('Y-m-d H:i:s', $dingStartTime),
            'work_date_to' => date('Y-m-d H:i:s', $filter['end_time'])
        ];

        // 查用户工作时长
        $workHouseList = teamones_request('teamones-work-hour', 'dingtalk/get_user_work_times', $paramData);

        $workHouseMap = [];
        if (!empty($workHouseList['data'])) {
            $workHouseMap = array_column($workHouseList['data'], null, 'user_id');
        }

        // 任务情况
        $saasUserIds = array_column($departmentUserList, 'saas_user_id');
        $notTime = time();
        $taskData = model(TaskModel::class)
            ->join("version on version.module_id = " . module_by_code('task')['id'] . ' and version.link_id = task.id', 'left')
            ->where(['task.project_id' => $filter['project_id'], 'task.step_type' => TaskModel::STEP_TYPE_STEP, 'task.executor' => ['IN', $saasUserIds]])
            ->where([['task.plan_end_time' => ['EGT', $filter['start_time']]], ['task.plan_end_time' => ['ELT', $filter['end_time']]]])
            ->field("from_unixtime(task.plan_end_time,'%Y-%m') as plan_end_time_ym,count(task.plan_end_time <= {$notTime} or null) abnormal_num,task.executor as task_executor,count(distinct task.id) as task_num,count(version.id) as submit_num,count(version.is_publish='yes' or null) published_number")
            ->group('task.executor')
            ->select();

        $taskMap = array_column($taskData, null, 'task_executor');
        $passTateMonthLoopRate = 0;// 通过率-月环比
        $finalRateMonthLoopRate = 0;  // 完成率-月环比
        if (!empty($filter['month'])) {  // 只查一个月,才有月环比
            $tmpTaskData = [];
            $lastTaskNum = 0;
            $nowTaskNum = 0;
            $nowPassNum = 0;
            $lastPassNum = 0;
            $nowSubmitNum = 0;
            $lastSubmitNum = 0;
            $lastMont = date('Y-m', strtotime('-1 month', strtotime($filter['month'])));
            foreach ($taskData as $item) {
                // 本月
                if ($item['plan_end_time_ym'] == $filter['month']) {
                    $tmpTaskData[] = $item;
                    $nowTaskNum += $item['task_num']; // 本月任务数
                    $nowPassNum += $item['published_number']; // 本月通过数
                    $nowSubmitNum += $item['submit_num']; // 本月提交次数
                }
                // 上月
                if ($item['plan_end_time_ym'] == $lastMont) {
                    $lastTaskNum += $item['task_num'];  // 上一个月的任务总数
                    if (!empty($item['published_number']) && $item['published_number'] > 0) {
                        $lastSubmitNum += $item['submit_num']; // 上一个月的提交次数
                    }
                    if (!empty($item['published_number']) && $item['published_number'] > 1) {
                        $lastPassNum += $item['published_number']; // 上一个月的通过数
                    }
                }
                if (!empty($lastTaskNum) && !empty($nowTaskNum)) { // 上月任务 - 本月任务
                    $tmpTaskNum = $lastTaskNum - $nowTaskNum;
                }
                if (!empty($lastPassNum) && !empty($nowPassNum)) { // 上月通过 - 本月通过
                    $tmpPassNum = $lastPassNum - $nowPassNum;
                }
                if (!empty($tmpPassNum) && !empty($tmpTaskNum)) { // 完成率-月环比
                    $finalRateMonthLoopRate = $tmpPassNum / $tmpTaskNum;
                }
                if (!empty($nowSubmitNum) && !empty($lastSubmitNum)) {
                    $tmpSubmitNum = $nowSubmitNum - $lastSubmitNum;
                }
                if (!empty($tmpSubmitNum) && $lastPassNum) {   // 通过率 = 任务版本通过次数 / 任务版本提交次数
                    $passTateMonthLoopRate = $lastPassNum / $tmpSubmitNum;
                }

            }
            // 本月任务数据
            $taskMap = array_column($tmpTaskData, null, 'task_executor');
        }

        $list = array_map(function ($tmp) use ($workHouseMap, $taskMap) {

            $taskItem = $taskMap[$tmp['saas_user_id']] ?? [];
            $averageHour = [];
            $workHourArr = $workHouseMap[$tmp['id']] ?? [];
            if (!empty($workHourArr['work_every_day_min'])) {
                $averageHour = array_filter($workHourArr['work_every_day_min'], function ($tmp) {
                    return $tmp > 0;
                });
            }
            $averageHour = array_map(function ($tmp) {
                return $tmp / 60;
            }, $averageHour);
            $averageHourNum = 0;
            if (!empty(array_sum($averageHour)) && !empty(count($averageHour))) {
                $averageHourNum = array_sum($averageHour) / count($averageHour);
            }

            $passPercent = 0;
            if (!empty($taskItem['published_number']) && $taskItem['published_number'] > 1) {
                // 通过率 = 任务版本通过次数 / 任务版本提交次数
                $passPercent = $taskItem['published_number'] / $taskItem['submit_num'];
            }
            $finalRate = 0;
            if (!empty($taskItem['published_number']) && $taskItem['published_number'] > 1) {
                $finalRate = $taskItem['published_number'] / $taskItem['task_num'];
            }
            $tmp['work_hour_info'] = $workHourArr;
            $tmp['work_hour_info']['average_hour_num'] = sprintf("%.2f", $averageHourNum);
            $tmp['pass_percent'] = sprintf("%.2f", $passPercent); // 通过率
            $tmp['final_rate'] = sprintf("%.2f", $finalRate); // 完成率
            $tmp['task_num'] = $taskItem['task_num'] ?? 0; // 任务量
            $tmp['average_hour_num'] = sprintf("%.2f", $averageHourNum); // 平均工时
            $tmp['published_number'] = $taskItem['published_number'] ?? 0; // 审批通过次数
            $tmp['submit_num'] = $taskItem['submit_num'] ?? 0; // 提交次数
            return $tmp;
        }, $departmentUserList);

        $totalWorkHour = 0;
        foreach ($list as $item) {
            $totalWorkHour += $item['work_hour_info']['average_hour_num'];
        }

        $workUser = array_filter($list, function ($tmp) {
            return intval($tmp['work_hour_info']['average_hour_num']) > 0;
        });

        // 钉钉工作总时长
        $dingWorkHour = 0;
        if (!empty($totalWorkHour) && !empty(count($workUser))) {
            $dingWorkHour = $totalWorkHour / count($workUser);
        }
        $abnormalTaskNum = 0; // 异常任务
        $finalRate = 0; // 完成率
        $totalTaskNum = 0;
        $totalPassNum = 0;
        foreach ($taskMap as $taskItem) {
            $abnormalTaskNum += $taskItem['abnormal_num'];
            $totalTaskNum += $taskItem['task_num'];
            if (!empty($taskItem['published_number']) && $taskItem['published_number'] > 1) {
                $totalPassNum += $taskItem['published_number'];
            }
        }
        if (!empty($totalPassNum) && !empty($totalTaskNum)) {
            $finalRate = $totalPassNum / $totalTaskNum;
        }
        $TotalPassTateNum = 0;
        $totalPassTatePeopleNum = 0;
        foreach ($list as $listItem) {
            if ($listItem['pass_percent'] > 0) {
                $totalPassTatePeopleNum++;
            }
            if ($listItem['pass_percent'] > 0) {
                $TotalPassTateNum += $listItem['pass_percent'];
            }
        }

        // 通过率
        $passTate = 0;
        if (!empty($totalPassTatePeopleNum) && !empty($TotalPassTateNum)) {
            $passTate = $TotalPassTateNum / $totalPassTatePeopleNum;
        }
        $totalInfo = [
            'final_rate' => sprintf("%.2f", $finalRate), // 完成率
            'final_rate_month_loop_rate' => sprintf("%.2f", $finalRateMonthLoopRate), // 完成率-月环比
            'pass_tate' => sprintf("%.2f", $passTate), // 通过率
            'pass_tate_month_loop_rate' => sprintf("%.2f", $passTateMonthLoopRate), // 通过率-月环比
            'abnormal_task_num' => $abnormalTaskNum, // 异常任务
            'ding_work_hour' => sprintf("%.2f", $dingWorkHour), // 平均钉钉工时
        ];

        multiple_sort_by($list, ['task_num' => 'desc', 'final_rate' => 'desc', 'pass_percent' => 'desc', 'average_hour_num' => 'desc']);
        return [
            'list' => $list,
            'total_info' => $totalInfo
        ];
    }


    /**
     * 部门报表-列表
     * @param $filter
     * @param $param
     * @param $isAbnormal
     * @param $category
     * @param $grade
     * @param $page
     * @return array
     */
    public function detail($filter, $param, $isAbnormal, $category, $grade, $page)
    {
        $param['start_time'] = strtotime($param['start_time']);
        $param['end_time'] = strtotime('+1 month', strtotime($param['end_time']));

        $entityFields = [
            "task.id as task_id",
            'task.created_by as task_crated_by',
            'task.project_id as task_project_id',
            'task.plan_end_time as task_plan_end_time',
            'task.executor as task_executor',
            "entity.name as entity_name",
            "entity.id as entity_id",
            "entity.initial_episode_code as initial_episode_code",
            "entity.showings_number as showings_number",
            'm.code as module_code',
            "step.name as step_name",
            "step.id as step_id",
            "step_category.name as step_category_name",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',m.code,'_category'))) as category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',m.code,'_grade'))) as grade",
        ];

        if ($isAbnormal) {
            $filter['task.plan_end_time'] = ['ELT', time()]; // 逾期异常
        }
        // 类型筛选
        if (!empty($category)) {
            $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', m.code, '_category')))"] = ['IN', $category];
        }
        // 等级筛选
        if (!empty($grade)) {
            $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', m.code, '_grade')))"] = ['IN', $grade];
        }

        $departmentUserList = $this->getDepartmentUserList($param['department_id']);

        $entityData = model(EntityModel::class)
            ->join('task on task.entity_id = entity.id')
            ->join('step on task.step_id = step.id')
            ->join('step_category on step.step_category_id = step_category.id')
            ->join('module m on m.id = entity.module_id')
            ->where(['task.executor' => ['IN', array_column($departmentUserList, 'saas_user_id')]])
            ->where(['task.step_type' => TaskModel::STEP_TYPE_STEP])
            ->where([['task.plan_end_time' => ['EGT', $param['start_time']]], ['task.plan_end_time' => ['ELT', $param['end_time']]]])
            ->where($filter)
            ->page($page[0], $page[1])
            ->field($entityFields)
            ->select();

        if (empty($entityData)) {
            return [];
        }

        // 用户信息
        $userIds = [];
        foreach ($entityData as $item) {
            if (!empty($item['task_crated_by'])) {
                $userIds[] = $item['task_crated_by'];
            }
            if (!empty($item['task_executor'])) {
                $userIds[] = $item['task_executor'];
            }
        }

        $userList = model(UserModel::class)->where(['id' => ['IN', $userIds]])->select();
        $userMap = array_column($userList, null, 'id');

        return array_map(function ($tmp) use ($userMap) {

            if ($tmp['task_plan_end_time'] < time()) {
                $startTime = date('Y-m-d', $tmp['task_plan_end_time']);
                $endTime = date('Y-m-d', time());
                $overdueDay = date_diff(date_create($startTime), date_create($endTime));
            }

            $tmp['created_by_info'] = $userMap[$tmp['task_crated_by']] ?? [];
            $tmp['executor'] = $userMap[$tmp['task_executor']] ?? [];
            $tmp['abnormal_info'] = [
                'overdue_day' => $overdueDay->days ?? 0, // 逾期天数
            ];
            return $tmp;
        }, $entityData);
    }

    /**
     * 获取部门用户信息
     * @param $departmentId
     * @return array
     */
    public function getDepartmentUserList($departmentId)
    {
        $paramData = [
            'param' => [
                'filter' => [
                    'department.id' => $departmentId,
                    'active' => UserModel::IM_USER_ACTIVE_OPEN
                ]
            ]
        ];

        // 查部门用户信息
        $selectUserList = teamones_request('teamones-im', 'department/select_user_list', $paramData);
        if (empty($selectUserList['data'])) {
            return [];
        }

        // 匹配 sass 用户id
        $saasUserList = model(UserModel::class)
            ->where(['union_id' => ['IN', array_column($selectUserList['data'], 'id')]])
            ->field('id,union_id')
            ->select();
        $saasUserMap = array_column($saasUserList, null, 'union_id');

        return array_map(function ($tmp) use ($saasUserMap) {
            $tmp['saas_user_id'] = $saasUserMap[$tmp['id']]['id'] ?? 0;
            $tmp['im_user_id'] = $saasUserMap[$tmp['id']]['union_id'] ?? 0;
            return $tmp;
        }, $selectUserList['data']);
    }
}


